package com.yunjian.admin.controller;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;

import java.util.Date;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.DisabledAccountException;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.yunjian.admin.vo.Constant;
import com.yunjian.admin.vo.SUserVo;
import com.yunjian.admin.vo.WebResult;
import com.yunjian.core.basic.model.SDataDic;
import com.yunjian.core.basic.model.SDataDicKey;
import com.yunjian.core.basic.model.SUser;
import com.yunjian.core.basic.service.CacheService;
import com.yunjian.core.basic.service.SDataDicService;
import com.yunjian.core.basic.service.SResourceService;
import com.yunjian.core.basic.service.SUserService;
import com.yunjian.core.basic.service.UserLogService;
import com.yunjian.core.basic.vo.CacheType;
import com.yunjian.core.busi.model.Employee;
import com.yunjian.core.busi.model.Store;
import com.yunjian.core.busi.service.EmployeeService;
import com.yunjian.core.busi.service.StoreService;

/**
 * 登录控制器
 * @author sonta
 *
 */
@Controller
@RequestMapping("/auth")
@Api(description="用户登录模块")
public class AuthController {
	private static final Logger logger = LoggerFactory.getLogger(AuthController.class);

	@Autowired
	private CacheService cacheService;
	@Autowired
	private SDataDicService sDataDicService;
	@Autowired
	private SUserService sUserService;
	@Autowired
	private SResourceService sResourceService;
	@Autowired
	private EmployeeService employeeService;
	@Autowired
	private StoreService storeService;
	@Autowired
	private UserLogService userLogService;
	
	@Value("${system.max-vc-gain-per-time}")
	private Integer MAX_VC_GAIN_PER_TIMES;
	

	/**
	 * 用户登录
	 * @param username
	 * @param password
	 * @param vc
	 * @param redirectAttributes
	 * @return
	 */
	@ApiOperation(value="用户登录")
	@RequestMapping(value = "/tologin", method = {RequestMethod.GET, RequestMethod.POST})
	@ResponseBody
	public WebResult<SUserVo> login(@ApiParam(value="用户名")@RequestParam(required=true)String username, 
			@ApiParam(value="密码")@RequestParam(required=true)String password, 
			@ApiParam(value="验证码")String vc) {
		WebResult<SUserVo> ret = new WebResult<>();
		//Session session = SecurityUtils.getSubject().getSession();
		/*String sessionVc = (String)session.getAttribute(username);
		if (StringUtil.isEmpty(sessionVc)) {
			ret.setCoder(WebResult.Coder.C1003);
			logger.warn("用户[{}]-{}", username, ret.getMsg());
			return ret;
		}
		if (!sessionVc.equals(vc)) {
			ret.setCoder(WebResult.Coder.C1004);
			logger.warn("用户[{}]-{}", username, ret.getMsg());
			// 清除缓存的验证码
			// session.removeAttribute(username);
			return ret;
		}*/
		// 开始登录
		Subject currentUser = SecurityUtils.getSubject();
		UsernamePasswordToken token = new UsernamePasswordToken(username, password);
		SUser upUser = new SUser();
		try {
			currentUser.login(token);
			// 验证是否登录成功
			if (currentUser.isAuthenticated()) {
				logger.info("用户[{}]-登录认证通过", username);
				SUser user = (SUser)currentUser.getPrincipal();
				upUser.setUserId(user.getUserId());
				upUser.setPwdWrongTimes(0); // 清除错误次数
				upUser.setLastLoginIp(currentUser.getSession().getHost());
				upUser.setLastLoginTime(new Date());
				sUserService.updateByPrimaryKeySelective(upUser);
				Employee employee = employeeService.selectByPrimaryKey(user.getUserId());
				Store store = storeService.selectByPrimaryKey(employee.getStoreId());
				SUserVo userVo = new SUserVo();
				userVo.setUserId(user.getUserId());
				userVo.setStoreId(store.getStoreId());
				userVo.setName(employee.getName());
				userVo.setStoreName(store.getCity() + store.getName());
				userVo.setLastLoginIp(user.getLastLoginIp());
				userVo.setLastLoginTime(user.getLastLoginTime());
				userVo.setResources(sResourceService.selectCacheByUserId(user.getUserId()));
				ret.setAttach(userVo);
				currentUser.getSession().setAttribute(Constant.USERVO_SESSION_KEY, userVo);
				userLogService.info(user.getUserId(), SecurityUtils.getSubject().getSession().getHost(), "用户登录");
				return ret.setCoder(WebResult.Coder.SUCCESS);
			}
		} catch (UnknownAccountException uae) {
			ret.setCoder(WebResult.Coder.C1001);
			logger.error("用户[{}]登录错误-{}", username, ret.getMsg());
			return ret;
		} catch (IncorrectCredentialsException ice) {
			ret.setCoder(WebResult.Coder.C1002);
			logger.error("用户[{}]登录错误-{}", username, ret.getMsg());
			SUser user = sUserService.selectByUserMultiName(username);
			int maxWrongTimes = 5;
			SDataDic dic = sDataDicService.selectCacheByPrimaryKey(SDataDicKey.RMS_MAX_PWD_FAILD_TIMES);
			if (dic != null) {
				maxWrongTimes = Integer.valueOf(dic.getDicValue());
			}
			int currentWrongTimes = user.getPwdWrongTimes() + 1;
			logger.error("用户-{}-密码错误：{}次", username, currentWrongTimes);
			upUser.setUserId(user.getUserId());
			upUser.setPwdWrongTimes(currentWrongTimes);
			if (currentWrongTimes >= maxWrongTimes) {
				upUser.setIsLocked(1); // 锁定账户
				logger.error("用户-{}-已锁定", username);
			}
			sUserService.updateByPrimaryKeySelective(upUser);
			return ret;
		} catch (LockedAccountException lae) {
			// 用户已锁定
			ret.setCoder(WebResult.Coder.C1005);
			logger.error("用户[{}]登录错误-{}", username, ret.getMsg());
			return ret;
		} catch (ExcessiveAttemptsException eae) {
			ret.setCoder(WebResult.Coder.C1005);
			logger.error("用户[{}]登录错误-{}", username, ret.getMsg());
			return ret;
		} catch (DisabledAccountException eae) {
			ret.setCoder(WebResult.Coder.C1006);
			logger.error("用户[{}]登录错误-{}", username, ret.getMsg());
			return ret;
		} catch (AuthenticationException ae) {
			ret.setCoder(WebResult.Coder.C1002);
			logger.error("用户[{}]登录错误-{}", username, ret.getMsg());
			return ret;
		}
		return ret.setCoder(WebResult.Coder.ERROR);
	}
	
	/**
	 * 用户登出
	 * @param userId
	 * @return
	 */
	@ApiOperation(value="用户登出")
	@RequestMapping(value = "/logout", method = {RequestMethod.GET, RequestMethod.POST})
	@ResponseBody
	public WebResult<String> logout(@ApiParam(value="用户编号")@RequestParam(required=true)String userId) {
		WebResult<String> ret = new WebResult<>();
		Subject currentUser = SecurityUtils.getSubject();
		SUser user = (SUser) currentUser.getPrincipal();
		logger.info("用户[{}]准备登出 ", userId);
		if (user == null) {
			return ret.setCoder(WebResult.Coder.SUCCESS);
		}
		logger.info("session userid - {}", user.getUserId());
		if (user.getUserId().equals(userId)) {
			logger.info("用户[{}]-成功登出", user.getUserId());
			currentUser.logout();
			userLogService.info(user.getUserId(), SecurityUtils.getSubject().getSession().getHost(), "用户登出");
			return ret.setCoder(WebResult.Coder.SUCCESS);
		}
		
		return ret.setCoder(WebResult.Coder.ILLEGAL);
	}
	
	/**
	 * 发送短信验证码
	 * @param phoneNum
	 * @return
	 */
	@ApiOperation(value="获取登录手机验证码")
	@RequestMapping(value = "/sendLoginSMS", method = {RequestMethod.GET, RequestMethod.POST})
	@ResponseBody
	public WebResult<String> sendVerifyCode(@ApiParam(value="手机号码")@RequestParam(required=true)String phoneNum) {
		WebResult<String> ret = new WebResult<>();
		// 获取缓存中已获取验证码次数
		Integer cachedGainTimes = (Integer)cacheService.getCache(CacheType.LOGIN_VC_GAIN_TIMES.getCode(), phoneNum);
		if (MAX_VC_GAIN_PER_TIMES == null) {
			MAX_VC_GAIN_PER_TIMES = 5;
		}
		if (cachedGainTimes != null && cachedGainTimes >= 5) {
			ret.setCoder(WebResult.Coder.C1007);
			logger.warn("用户[{}]获取验证码-{}", phoneNum, ret.getMsg());
			return ret;
		}
		Session session = SecurityUtils.getSubject().getSession();
		String vc = "12345";
		session.setAttribute(phoneNum, vc);
		// 缓存验证码获取的次数
		cacheService.addCache(CacheType.LOGIN_VC_GAIN_TIMES.getCode(), phoneNum, cachedGainTimes == null ? 1 : cachedGainTimes++);
		userLogService.info(phoneNum, SecurityUtils.getSubject().getSession().getHost(), "发送短信验证码");
		return ret.setCoder(WebResult.Coder.SUCCESS);
	}
}
